#parse('/clickframes/seam/includes/getterSetter.vm')
#set ($controller = ${context.get($page).controller})
package ${techspec.packageName}.controller;

import ${techspec.packageName}.model.CustomIdentity;
#if ($page.loginRequired)
import ${techspec.packageName}.entity.${appspec.loginEntity.name};
#end
#foreach ($entity in $controller.uniqueEntities)
import ${techspec.packageName}.entity.${entity.name};
#end

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;

#if ($page.parametersDefined)
import org.jboss.seam.annotations.web.RequestParameter;
#end

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.event.ActionEvent;
#if ($page.anyDropdownInputsOnPage)
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;
#end
import java.util.Map;
#if ($page.outputLists || $page.anyFileInputsOnPage || $page.anyDropdownInputsOnPage)
import java.util.List;
#end
#if ($page.anyFileInputsOnPage || $page.anyDropdownInputsOnPage)
import ${techspec.packageName}.entity.UploadedFile;
import java.util.ArrayList;
import org.richfaces.model.UploadItem;


#end

/**
 * Glue code to bind $page.title Service with the view framework (Seam). This class contains
 * a default implementation of the action methods. Please avoid reimplmenting the action methods in this class.
 * The purpose of this class is to declare properties which can be bound to the UI.
 * 
 #if ($page.description) 
 * ${page.description}
 #end
 *
 * Automatically generated by clickframes
 * 
 * @author Vineet Manohar
 */
public abstract class Generated${page.name}Controller extends Controller {
## unique entities on this controller
#foreach ($entity in $controller.uniqueEntities)
    @In("#{${entity.id}Dao}") 
    protected ${techspec.packageName}.dao.${entity.name}Dao ${entity.id}Dao;

    @In("#{${entity.id}Service}") 
    protected ${techspec.packageName}.entity.service.${entity.name}Service ${entity.id}Service;

#end   

#if ($page.loginRequired)
    public ${appspec.loginEntity.name} getLoggedInUser() {
        return identity.get${appspec.loginEntity.name}();
    }
#end

#foreach ($pageEntity in ${controller.pageEntities})
#set ($entity = $pageEntity.entity)
#getterSetter({"type" : "${entity.name}", "id" : "${pageEntity.id}", "name" : "${pageEntity.name}", "title" : "${entity.title}", "description" : "${entity.description} - ${pageEntity.type}", "fieldVisibility" : "protected"})

    protected void init${pageEntity.name}() {
        // if ${outputList.id} has not been initialized, initialize it now
        if (get${pageEntity.name}() == null) {
            set${pageEntity.name}(load${pageEntity.name}());
        }
        
#if ($page.entitiesUpdated.get($pageEntity.entity))
        // updating all linked entities here
#set ($entityForm = $page.entitiesUpdated.get($pageEntity.entity))
        if (get${pageEntity.name}() != null) {
            // This entity is of type '${pageEntity.entity.id}'. There is a form on this page which 
            // updates an entity of type '${pageEntity.entity.id}'. Therefore, use this entity to prePopulate the inputs
#foreach ($input in $entityForm.entityInputs.get($pageEntity.entity))
#if ($input.entityProperty)
#if ($input.entityProperty.type == 'FILE')
            // set${entityForm.name}${input.name}(get${pageEntity.name}().get${input.entityProperty.name}().clone());
#else
            set${entityForm.name}${input.name}(get${pageEntity.name}().get${input.entityProperty.name}());
#end
#end ## if this input is bound to entity property
#end
        }
#end ## if any entities are updated
    }

    protected ${entity.name} load${pageEntity.name}() {
#if (${pageEntity.type} == 'PARAM_PRIMARY_KEY')
        return ${pageEntity.pageParameter.entityProperty.entity.id}Dao.findByPrimaryKey(${pageEntity.pageParameter.id});
#else
    return null;
#end
    }

    protected void reload${pageEntity.name}() {
        clear${pageEntity.name}();
        load${pageEntity.name}();
    }

    protected void clear${pageEntity.name}() {
        set${pageEntity.name}(null);
    }
#end ## // foreach

#foreach ($outputList in $page.outputLists)
    /** the ${outputList.entity.name} row which on which the action was performed is stored on 
     * this field via the corresponding action listener if a user performs an action on the 
     * displayed ${outputList.entity.name} list 
     */
#getterSetter({"type" : "$outputList.entity.name", "id" : "${outputList.id}Selection", "name" : "${outputList.name}Selection", "title" : "Selected $outputList.name", "description" : "Selected $outputList.name row"})

    public void ${outputList.id}Listener(ActionEvent actionEvent) {
        UIComponent tmpComponent = actionEvent.getComponent();

        while (null != tmpComponent && !(tmpComponent instanceof UIData)) {
            tmpComponent = tmpComponent.getParent();
        }

        UIData uiData = (UIData) tmpComponent;
        Object selectedRow = uiData.getRowData();
        if (selectedRow instanceof ${outputList.entity.name}) {
            this.${outputList.id}Selection = (${outputList.entity.name}) selectedRow;
        }
    }

#getterSetter({"type" : "List<$outputList.entity.name>", "id" : "$outputList.id", "name" : "$outputList.name", "title" : "$outputList.title", "description" : "$outputList.description"})

#end
    
	@SuppressWarnings("unused")
	private static final Log logger = LogFactory.getLog(Generated${page.name}Controller.class);

#if($appspec.securityEnabled)
	@In
	protected CustomIdentity identity;
#end

    @Create
    public void init() {
#foreach ($form in $page.forms)

#foreach($input in $form.dropdownOrRadioInputs)
        init${form.name}${input.name}();
#end

#if ($form.fileInputs)
        // initialize all file inputs
#foreach($input in $form.fileInputs)
        // ${form.id}${input.name} = new UploadedFile();
#end
#end ## if ($form.fileInputs)
#end ## foreach $form
        // all inputs initialized here 
    }

#foreach($pageParameter in $page.parameters)
	@RequestParameter
#getterSetter({"type" : "String", "id" : "${pageParameter.id}", "name" : "${pageParameter.name}", "title" : "${pageParameter.title}", "description" : "${pageParameter.description}"})
#end

#foreach ($output in $page.outputs)
#if (${context.get($output).generateEntityFieldInController})
#getterSetter({"type" : "${output.entity.name}", "id" : "${output.id}", "name" : "${output.name}", "title" : "${output.title}", "description" : "$output.description}"})
#end
#end

#foreach($outputList in $page.outputLists)## for each entity list, populate from the dao
    protected void init${outputList.name}() {
        // if ${outputList.id} has not been initialized, initialize it now
        if (get${outputList.name}() == null) {
            set${outputList.name}(load${outputList.name}());
        }
    }

    /**
     * clears the current value and loads the value again
     */
    protected void reload${outputList.name}() {
        clear${outputList.name}();
        load${outputList.name}();
    }

    /**
     * clears the current value of ${outputList.title} 
     */
    protected void clear${outputList.name}() {
        set${outputList.name}(null);
    }

    protected List<${techspec.packageName}.entity.${outputList.entity.name}> load${outputList.name}() {
        return ${outputList.entity.id}Dao.find${outputList.name}(describe());
    }

#end

	/**
	 * This method should be called before the page is loaded
	 * 
	 * All the page parameters should be consumed in this method
	 */    
    public String ${controller.pageLoadActionId}() {
## // from params
#foreach($pageParameter in $page.parameters) 
#if (${pageParameter.entityProperty} && ${pageParameter.entityProperty.primaryKey})
        init${pageParameter.entityProperty.entity.name}();
#end
#end

## // from outputLists
#foreach($outputList in $page.outputLists)## for each entity list, populate from the dao
        init${outputList.name}();

#end 

## // from outputs
#foreach($output in $page.outputs)## for each output, populate from the dao
#if (${context.get($output).generateEntityFieldInController})
        init${output.name}();
#end
#end
          // if you need to add more code, override this method in the child class

        return null;
    }

## // create the load method so that it can be customized separately 
#foreach($output in $page.outputs)
#if (${context.get($output).generateEntityFieldInController})
    protected ${output.entity.name} load${output.name}() {
        return ${output.entity.id}Dao.get${output.name}(describe());
    }
    
    protected void init${output.name}() {
        // if ${output.id} has not been initialized, initialize it now
        if (get${output.name}() == null) {
            set${output.name}(load${output.name}());
            
#if ($page.entitiesUpdated.get($output.entity))
#set ($entityForm = $page.entitiesUpdated.get($output.entity))
            if (get${output.name}() != null) {
                // this entity is of type '${output.entity.id}'. 
                // there is a form on this page which updates an entity of type '${output.entity.id}'.
                // therefore, use this entity to prePopulate the inputs
#foreach ($input in $entityForm.entityInputs.get($output.entity))
#if ($input.entityProperty)
#if ($input.entityProperty.type == 'FILE')
                set${entityForm.name}${input.name}(get${output.name}().get${input.entityProperty.name}().clone());
#else
                set${entityForm.name}${input.name}(get${output.name}().get${input.entityProperty.name}());
#end
#end ## if this input is bound to entity property
#end
            }
#end ## if any entities are updated
        }

    }
#end ##generateEntityFieldInController
#end

#### form inputs ####
#foreach ($form in $page.forms)
#foreach($textInput in $form.textOrPasswordInputs)
	/** ${textInput.title}
	 *
 #if ($textInput.description) 
	 * ${textInput.description}
 #end
	 */
   
#if(!($page.loginPage && $form.loginForm && ($input.loginUsername || $login.loginPassword)))	protected String ${form.id}${textInput.name};
#end

#foreach ($validation in $textInput.validations)
 #if ($validation.type == "email")
	@org.hibernate.validator.Email(message="$validation.authoredOrGeneratedDescription")
 #end
 #if ($validation.type == "required")
	@org.hibernate.validator.NotNull(message="$validation.authoredOrGeneratedDescription")
 #end
 #if ($validation.type == "length")
	@org.hibernate.validator.Length(#if ($validation.minDefined) min=$validation.min,#end #if ($validation.maxDefined) max=$validation.max, #end message="$validation.authoredOrGeneratedDescription")
 #end
#end
#if (${textInput.regexValidationsDefined})
	@org.hibernate.validator.Patterns(value = {
 #foreach ($regexValidation in $textInput.regexValidations)
	#if ($velocityCount != 1),#end
	@org.hibernate.validator.Pattern(regex = "$regexValidation.javaSafeRegex", message = "$regexValidation.authoredOrGeneratedDescription")
 #end
	})
#end
	public String get${form.name}${textInput.name}() {
#if(!$input.loginUsername && !$login.loginPassword)	   return this.${form.id}${textInput.name};
#else
  #if($input.loginUsername)		return identity.getUsername();
  #else		return identity.getPassword();
  #end
#end
	}

	public void set${form.name}${textInput.name}(String ${form.id}${textInput.name}) {
#if(!$input.loginUsername && !$login.loginPassword)		this.${form.id}${textInput.name} = ${form.id}${textInput.name};
#else
  #if($input.loginUsername)		identity.setUsername(${form.id}${textInput.name});
  #else		identity.setPassword(${form.id}${textInput.name});
  #end
#end
	}
#end

#foreach($checkboxInput in $form.checkboxInputs)
	/** ${checkboxInput.title}
	 *
 #if ($checkboxInput.description) 
	 * ${checkboxInput.description}
 #end
	 */
	protected boolean ${form.id}${checkboxInput.name};

	public boolean get${form.name}${checkboxInput.name}() {
		return this.${form.id}${checkboxInput.name};
	}

	public void set${form.name}${checkboxInput.name}(boolean ${form.id}${checkboxInput.name}) {
		this.${form.id}${checkboxInput.name} = ${form.id}${checkboxInput.name};
	}
#end

#foreach($input in $form.fileInputs)
#getterSetter({"type" : "UploadedFile", "id" : "${form.id}${input.name}", "name" : "${form.name}${input.name}", "title" : "${input.title}", "description" : "${input.description}"})
#getterSetter({"type" : "java.io.InputStream", "id" : "${form.id}${input.name}InputStream", "name" : "${form.name}${input.name}InputStream", "title" : "${input.title} Data", "description" : "${input.description} Data"})
#getterSetter({"type" : "String", "id" : "${form.id}${input.name}ContentType", "name" : "${form.name}${input.name}ContentType", "title" : "${input.title} ContentType", "description" : "${input.description} ContentType"})
#getterSetter({"type" : "String", "id" : "${form.id}${input.name}FileName", "name" : "${form.name}${input.name}FileName", "title" : "${input.title} File name", "description" : "${input.description} File name of uploaded file"})
#end

#foreach($input in $form.dropdownOrRadioInputs)
#set($inputContext = $context.get($input))
    protected void init${form.name}${input.name}() {
#foreach($allowedValueKey in $input.allowedValues.keySet())
        this.${form.id}${input.name}Options.add(new SelectItem("${allowedValueKey}", "$input.allowedValues.get(${allowedValueKey})"));
#end## foreach($allowedValueKey
    }

 /** ${input.title}
  *
  * #if ($input.description) ${input.description} 
    #end
  */
  protected $inputContext.javaType ${form.id}${input.name};
  
  public $inputContext.javaType get${form.name}${input.name}() {
    return this.${form.id}${input.name};
  }

  public void set${form.name}${input.name}($inputContext.javaType ${form.id}${input.name}) {
    this.${form.id}${input.name} = ${form.id}${input.name};
  }

  protected List<SelectItem> ${form.id}${input.name}Options = new ArrayList<SelectItem>();

  public List<SelectItem> get${form.name}${input.name}Options() {
    return this.${form.id}${input.name}Options;
  }

  public void set${form.name}${input.name}Options(List<SelectItem> ${form.id}${input.name}Options) {
    this.${form.id}${input.name}Options = ${form.id}${input.name}Options;
  }
#end## foreach($input 
#end #### end form inputs ####

#foreach ($form in $page.forms) ### form level actions

	/**
	 * a convenient method to clear this form
	 */
	protected void clear${form.name}() {
#foreach ($input in ${form.inputs})
		clear${form.name}${input.name}();
#end
	}

#foreach ($input in $form.inputs) ### form inputs
    public void clear${form.name}${input.name}() {
#if ($input.type == 'upload')
	set${form.name}${input.name}ContentType(null);
	set${form.name}${input.name}InputStream(null);
	set${form.name}${input.name}FileName(null);
#else
		set${form.name}${input.name}(null);
#end
    }

    public void ${form.id}${input.name}Validator(javax.faces.context.FacesContext facesContext,
            javax.faces.component.UIComponent component, java.lang.Object value) {
        String valueStr = value.toString();
        
#if ($input.matchesInputValidation)        
        boolean valid = StringUtils.equals(get${form.name}${input.matchesInputValidation.otherInputName}(), valueStr);

        if (!valid) {
            FacesMessage message = new FacesMessage();
            message.setDetail("${input.matchesInputValidation.authoredOrGeneratedDescription}");
            message.setSummary("${input.matchesInputValidation.authoredOrGeneratedDescription}");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new javax.faces.validator.ValidatorException(message);
        }
#end##if
    }
#end## #foreach input
#end## #foreach forms

#foreach ($form in $page.forms) ### form level actions

#foreach ($entity in ${form.entityInputs.keySet()})
    /**
     *  Converts any form inputs bound to entities to entities, stores them in the map ready to 
     *  be passed to the service methods
     */
    protected $entity.name get${form.name}${entity.name}() {
#if ($form.updateForm) ## // if we are editing an entity
    #set($entityVar = "${entity.id}")
#else ## // if we are not editing an entity
#set($entityVar = "new${entity.name}")
        // create a new $entity.name from input
        ${entity.name} $entityVar = ${entity.id}Dao.newInstance();
#end

#foreach ($input in ${form.entityInputs.get($entity)})
#if ($input.entityProperty.type == 'FILE')
        ${entityVar}.get${input.entityProperty.name}().update($form.id${input.name}FileName, $form.id${input.name}ContentType, $form.id${input.name}InputStream);
#else
        ${entityVar}.set${input.entityProperty.name}(to${input.entityProperty.type.name}#if($input.entityProperty.multiple)List#{end}($form.id$input.name));
#end
#end
        return ${entityVar};
    }

#end## foreach $entity

#foreach ($action in $form.actions) ### special case for login action on login page
#if($action.loginAction)
   public ${form.name}${action.name}Outcome ${form.id}${action.name}() {
      // logout first if already logged in
      if (identity.isLoggedIn(false)) {
          identity.logout();
      }

       // call seam
      String seamOutcome = identity.login();

      if (seamOutcome != null && seamOutcome.equals("loggedIn")) {
          return convertSuccessfulSeamOutcomeToApplicationOutcome();
      }

      // convert seam outcome into clickframes outcome
      return ${form.name}${action.name}Outcome.${action.loginFailedOutcome.id};
   }
#else

   /**
    * ${action.title}
    *
    * #if ($action.description)${action.description}#end
    * Automatically generated by clickframes
    */
   public abstract ${form.name}${action.name}Outcome ${form.id}${action.name}();
#end
#end
#end

#if($page.loginPage)
   public boolean authenticate() {
#if ($appspec.loginEntity)
     ${appspec.loginEntity.name} ${appspec.loginEntity.id} = ${appspec.loginEntity.id}Dao.findByUsernameAndPassword(${page.loginForm.id}${page.loginForm.loginUsernameInput.name}, ${page.loginForm.id}${page.loginForm.loginPasswordInput.name});
        
     // store user for the session
     identity.set${appspec.loginEntity.name}(${appspec.loginEntity.id});

     // identity.setRememberMe(false);
       
     // return outcome
     return ${appspec.loginEntity.id} != null;
#else
     // login always succeeds, override this in child controller
     return true;
#end
   }
#end

#if($page.loginPage)

    protected ${page.loginForm.name}${page.loginForm.loginAction.name}Outcome convertSuccessfulSeamOutcomeToApplicationOutcome() {
        return ${page.loginForm.name}${page.loginForm.loginAction.name}Outcome.${page.loginForm.loginAction.loginSuccessfulOutcome.id};
    }
#end

#foreach ($email in $page.emails)
    @In(create=true)
#getterSetter({"type" : "${techspec.packageName}.email.${email.name}Email", "id" : "${email.id}Email", "name" : "${email.name}Email", "title" : "${email.title}", "description" : "${email.description}"})

#end

    private static final long serialVersionUID = 1L;

#foreach ($form in $page.forms)

#foreach ($action in $form.actions)
    /**
     * different legal outcomes for $action.title 
     * 
     * $!{page.description}
     */
     public enum ${form.name}${action.name}Outcome {
#set($index = 0)
#foreach ($outcome in $action.outcomes)
        /** 
         * ${outcome.title}
         */ 
        ${outcome.id}#if ($index < $action.outcomes.size() - 1),#end 
#set ($index = $index + 1)
    
#end
    }
#end ## $action
#end ## $form
}